/**
 * @file battery_test_iio.c
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2023-12-17
 * 
 * @copyright Copyright (c) 2023
 * 
 */


#include <linux/iio/iio.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/types.h>
#include <uapi/linux/iio/types.h>
#include <linux/hrtimer.h>
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/workqueue.h>

//modified为1时，channel2 通道修饰符，对于加速度器这种多通道的设备有用，影响sysfs下面的名称 见: iio_modifier
//info_mask_separate 有此通道单独使用
//info_mask_shared_by_type 由type相同通道的一起使用
//scan_index是扫描索引, 当使用触发缓冲区的时候
//indexed为1的时候，channel为通道索引
#define TEST_CHANNEL(_type, _axis, _index) {\
	.type = _type, \
	.modified = 1, \
	.channel2 = IIO_MOD_##_axis, \ 
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), \
	.scan_index = _index, \
	.scan_type = { \
		.sign = 's', \
		.realbits = 16, \
		.storagebits = 16, \
		.endianness = IIO_LE, \
	}, \
	}



#define TEST_TEMP_CHAN(_index) \
	{ \
		.type = IIO_TEMP, \
		.indexed = 1, \
		.channel = 0, \
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
				      BIT(IIO_CHAN_INFO_OFFSET) | \
				      BIT(IIO_CHAN_INFO_SCALE), \
		.scan_index = _index, \
		.scan_type = { \
			.sign = 's', \
			.realbits = 16, \
			.storagebits = 16, \
			.endianness = IIO_LE, \
		}, \
	}


enum test_scan_index {
	TEST_SCAN_GYRO_X = 0,
	TEST_SCAN_GYRO_Y,
	TEST_SCAN_GYRO_Z,
	TEST_SCAN_ACCEL_X,
	TEST_SCAN_ACCEL_Y,
	TEST_SCAN_ACCEL_Z,
	TEST_SCAN_TEMP,
	TEST_SCAN_TIMESTAMP,
};

static const struct iio_chan_spec test_channels[] = {
	TEST_CHANNEL(IIO_ACCEL, X, TEST_SCAN_ACCEL_X),
	TEST_CHANNEL(IIO_ACCEL, Y, TEST_SCAN_ACCEL_Y),
	TEST_CHANNEL(IIO_ACCEL, Z, TEST_SCAN_ACCEL_Z),
	TEST_CHANNEL(IIO_ANGL_VEL, X, TEST_SCAN_GYRO_X),
	TEST_CHANNEL(IIO_ANGL_VEL, Y, TEST_SCAN_GYRO_Y),
	TEST_CHANNEL(IIO_ANGL_VEL, Z, TEST_SCAN_GYRO_Z),
	TEST_TEMP_CHAN(TEST_SCAN_TEMP),
	IIO_CHAN_SOFT_TIMESTAMP(TEST_SCAN_TIMESTAMP),
};

//chan->type, chan->channel2
static int bmi270_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan, int *val,
			   int *val2, long mask)
{
	int ret = 0
	
	
	
	;
	//struct bmi270_data *data = iio_priv(indio_dev);
    printk("iio read %d", mask);
	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		*val = 1000;
		return ret ? ret : IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		*val = 0;
		*val2 = 1000000;
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_SAMP_FREQ:
		*val = 0;
        *val2 = 1000000; 
		return IIO_VAL_INT_PLUS_MICRO;
	default:
		return -EINVAL;
	}

	return 0;
}

static int bmi270_write_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan, int val, int val2,
			    long mask)
{
    printk("iio write %d %d %d", mask, val, val2);
	switch (mask) {
	case IIO_CHAN_INFO_SCALE:
		return 0;
		break;
	case IIO_CHAN_INFO_SAMP_FREQ:
		return 0;
	default:
		return -EINVAL;
	}

	return 0;
}


static const struct iio_info bmi270_info = {


	.read_raw = bmi270_read_raw,
	.write_raw = bmi270_write_raw,
};

static irqreturn_t bmi270_trigger_handler(int irq, void *p)
{
	// struct iio_poll_func *pf = p;
	// struct iio_dev *indio_dev = pf->indio_dev;
    printk("--------->\n");

    return IRQ_HANDLED;
}

int test_iio_init(struct device *dev)
{
    struct iio_dev *indio_dev;
	printk("start load iio\n");
    indio_dev = devm_iio_device_alloc(dev, 10);
	if (!indio_dev)
		return -ENOMEM;
    printk("start load iio 1\n");
	indio_dev->channels = test_channels;
	indio_dev->num_channels = ARRAY_SIZE(test_channels);
	indio_dev->name = "test";
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->info = &bmi270_info;

    printk("start load iio 2\n");
    int	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
					      iio_pollfunc_store_time,
					      bmi270_trigger_handler, NULL);
    printk("start load iio 3\n");
    return devm_iio_device_register(dev, indio_dev);
}

EXPORT_SYMBOL_GPL(test_iio_init);


MODULE_LICENSE("GPL");
